home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Diamond Collection / The Diamond Collection (Software Vault)(Digital Impact).ISO / cdr40 / x1j4_src.zip / L2B.C < prev    next >
Text File  |  1995-01-21  |  43KB  |  870 lines

  1. /**************************************************************************\
  2. *                                                                          *
  3. *                                                                          *
  4. *    *****                      *****                                      *
  5. *      *****                  *****                                        *
  6. *        *****              *****                                          *
  7. *          *****          *****                                            *
  8. *            *****      *****                                              *
  9. *              *****  *****                                                *
  10. *            *****      *****                                              *
  11. *          *****          *****          The Firmware. The Net.            *
  12. *        *****              *****        Portable. Compatible.             *
  13. *      *****                  *****      Public Domain.                    *
  14. *    *****                      *****    By NORD><LINK.                    *
  15. *                                                                          *
  16. *                                                                          *
  17. *                                                                          *
  18. *    L2B.C   -   Level 2, Teil 2                                           *
  19. *                                                                          *
  20. *    angelegt:      DC4OX                                                  *
  21. *    modifiziert:                                                          *
  22. *           Use of register keyword - April 1991 G8KBB                     *
  23. *           Add second part of heard list support - check PID for L3/4 etc * 
  24. *           add link to IP router in 'tol3sw' to forward L2 encap frames   *
  25. *           add parameter to splcpy to control when it is OK to split      *
  26. *           remove spurious '== 1' and similar                             *
  27. *                                                                          *
  28. * September 1993 - released as TheNet X-1J                                 *
  29. *                                                                          *
  30. * Added support for texnet in heard list in tol3sw()                       *
  31. * Correct digi bug ( didn't copy kiss digipeated frames )                  *
  32. *                                                                          *
  33. * Released as TheNet X-1J release 4, January 1995                          *
  34. \**************************************************************************/
  35.  
  36.  
  37. /*                                                             Includes   */
  38. /**************************************************************************/
  39.  
  40. #include "all.h"         /* allgemeine Festlegungen                       */
  41. #include "tntyp.h"       /* Festlegungen/Datenstrukturen fuer den Level 2 */
  42. #include "l2s.h"         /* Zugriff auf die State-Tabellen                */
  43. #include "l2ext.h"       /* globale Variable / nicht int-Funktionen       */
  44.  
  45.  
  46. /**************************************************************************\
  47. *                                                                          *
  48. * "check no activity"                                                      *
  49. *                                                                          *
  50. * Alle aktiven Links (lnktbl, Linkstatus "Information Transfer") auf       *
  51. * "keine Aktivitaet" abtesten. Ist der Keine-Aktivitaet-Timer aktiv (!= 0) *
  52. * und nach Dekrementieren abgelaufen, Disconnect einleiten.                *
  53. *                                                                          *
  54. * ACHTUNG: Diese Funktion muss sekuendlich aufgerufen werden,              *
  55. *          wird aber nur fuer TheNet benoetigt.                            *
  56. *                                                                          *
  57. \**************************************************************************/
  58.  
  59. #ifndef FIRMWARE
  60.  
  61. VOID chknoa()
  62.   {
  63.     register unsigned n;
  64.     
  65.     for (n = LINKNMBR, lnkpoi = lnktbl; n != 0; --n, ++lnkpoi)
  66.       if (lnkpoi->state >= L2SIXFER)
  67.         if (lnkpoi->noatou != 0 && !(--lnkpoi->noatou)) disc();
  68.   }
  69.  
  70. #endif
  71.  
  72.  
  73.  
  74.  
  75.  
  76. /**************************************************************************\
  77. *                                                                          *
  78. * "new link"                                                               *
  79. *                                                                          *
  80. * Link (lnkpoi) neu aufbauen. Wenn Link noch nicht aktiv war, die Anzahl   *
  81. * aktiver Links (nmblks) erhoehen.                                         *
  82. *                                                                          *
  83. \**************************************************************************/
  84.  
  85. VOID newlnk()
  86.   {
  87.     reslnk();                           /* Sequenzvars/Timer ruecksetzen  */
  88.     setiT1();                           /* FRACK-Timer neu starten        */
  89.     txfV2 = lnkpoi->V2link;             /* welche Protokollversion        */
  90.     xsabm();                            /* SABM senden                    */
  91.     if (lnkpoi->state == L2SDSCED)      /* neuer Link ?                   */
  92.       ++nmblks;                         /* ja ...                         */
  93.     lnkpoi->state = L2SLKSUP;           /* Linkstatus "Link Setup"        */
  94.   }
  95.  
  96.  
  97.  
  98.  
  99.  
  100. /**************************************************************************\
  101. *                                                                          *
  102. * "disconnect link"                                                        *
  103. *                                                                          *
  104. * Disconnect-Wunsch an aktuellen Link (lnkpoi) :                           *
  105. *                                                                          *
  106. *   Linkstatus "Disconnected"                                              *
  107. *   -> Ax.25-Parameter "frisch"                                            *
  108. *                                                                          *
  109. *   Linkstatus "Link Setup" oder "Disconnect Request"                      *
  110. *   -> Link aufloesen, neuer Linkstatus "Disconnected"                     *
  111. *                                                                          *
  112. *   sonst                                                                  *
  113. *   -> Empfangsinfoframeliste loeschen, Linkstatus bleibt, Flag "nach      *
  114. *      Loswerden aller zu sendenden Infoframes disconnecten" setzen        *
  115. *                                                                          *
  116. \**************************************************************************/
  117.  
  118. VOID dsclnk()
  119.   {
  120.     register unsigned lstate;
  121.  
  122.     if (!(lstate = lnkpoi->state))                     /* Disced, nur     */
  123.       inilbl();                                        /* AX-Pars neu     */
  124.     else
  125.       if (lstate == L2SLKSUP || lstate == L2SDSCRQ)    /* Linksetup oder  */
  126.         {                                              /* Discreq,        */
  127.           clrlnk();                                    /* Link aufloesen  */
  128.           lnkpoi->state = L2SDSCED;                    /* Diconnected !   */
  129.         }
  130.       else
  131.         {                                              /* sonst           */
  132.           dealml(&lnkpoi->rcvdil);                     /* RX-Infoframe-   */
  133.           lnkpoi->rcvd = 0;                            /* loeschen und    */
  134.           lnkpoi->flag |= L2FDSLE;                     /* Flag, s.o.      */
  135.         }
  136.   }
  137.  
  138.  
  139.  
  140.  
  141.  
  142. /**************************************************************************\
  143. *                                                                          *
  144. * "information to link"                                                    *
  145. *                                                                          *
  146. * Infobuffer, auf den imbp zeigt, an in diesem Buffer festgelegten Link    *
  147. * (l2link) zwecks Aussendung als Paket weitergeben. Wenn nocgnc == YES     *
  148. * keine "Erstickungskontrolle", sonst conctl beachten (s.u.).              *
  149. * Der Infobuffer wird bei Weitergabe an den Link mit der normalen Level 2  *
  150. * PID versehen, der Keine-Aktivitaets-Timer wird neu gestartet.            *
  151. *                                                                          *
  152. * Return:  TRUE  - imbp wurde angenommen und an den Link weitergegeben     *
  153. *          FALSE - imbp wurde nicht angenommen wegen Congestion Control    *
  154. *                  = Grenze der pro Link maximal zu speichernden Pakete    *
  155. *                    (conctl) wuerde ueberschritten werden                 *
  156. *                                                                          *
  157. \**************************************************************************/
  158.  
  159. BOOLEAN itolnk(nocgnc,imbp)
  160. BOOLEAN    nocgnc;                      /* "no congestion control"        */
  161. register MBHEAD    *imbp;               /* "I message buffer pointer"     */
  162.  
  163.   {
  164.     register LNKBLK *linkp;
  165.  
  166.     if ((linkp = imbp->l2link)->tosend < conctl || nocgnc /* == YES */ )
  167.       {
  168.         imbp->l2fflg = L2CPID;                    /* Standard-L2-PID      */
  169.         relink(unlink(imbp),linkp->sendil.tail);  /* -> ab in den Link    */
  170.         ++linkp->tosend;                          /* ein Sendepaket mehr  */
  171.         linkp->noatou = ininat;                   /* wieder Aktivitaet    */
  172.         return (TRUE);                            /* ... imbp angenommen  */
  173.       }
  174.     return (FALSE);                               /* ... imbp abgelehnt   */
  175.   }
  176.  
  177.  
  178.  
  179.  
  180.  
  181. /**************************************************************************\
  182. *                                                                          *
  183. * "digipeat"                                                               *
  184. *                                                                          *
  185. * Framebuffer, auf den fbp zeigt, abtesten, ob er ein zu digipeatendes     *
  186. * Paket enthaelt. Wenn ja, Paket an den entsprechenden Port (falls ein     *
  187. * bekannter Nachbarknoten direkt in der Digiliste folgt oder nach          *
  188. * kompletten Digipeaten das Ziel ist, kann das Paket auch auf einem        *
  189. * anderen als dem normalen HDLC-Port digipeatet werden) ausgeben.          *
  190. * Das Paket muss schon durch takfhd() analysiert sein, die rxf...-         *
  191. * Parameter muessen gesetzt sein.                                          *
  192. *                                                                          *
  193. * Return:  YES - das Frame wurde entweder digipeatet, oder der             *
  194. *                Framebuffer wurde deallokiert, weil das Frame noch von    *
  195. *                einer anderen Station digipeatet werden muss oder ich     *
  196. *                nicht digipeaten darf                                     *
  197. *          NO  - das Frame muss nicht mehr digipeated werden, hat alle     *
  198. *                noetigen Digipeater durchlaufen, ist zur Auswertung frei  *
  199. *                                                                          *
  200. \**************************************************************************/
  201.  
  202. BOOLEAN digipt(fbpx)
  203. MBHEAD *fbpx;
  204.  
  205.   {
  206.     register unsigned    n;                       /* Zaehler              */
  207.     register char       *viap;                    /* Zeiger in via-Liste  */
  208.     register MBHEAD *fbp = fbpx;
  209.     
  210.     viap = rxfhdr + L2ILEN;                       /* Anfang via-Liste     */
  211.     while (*viap != '\0')                         /* via-Liste durchgehen */
  212.       {
  213.         if (!(viap[L2IDLEN - 1] & L2CH))          /* zu digipeaten ?      */
  214.           {
  215.             if (Rpar == YES && istome(viap) /*== TRUE*/)/* ja, darf ich    */
  216.               {                                        /* und muss ich :  */
  217.                 rwndmb(fbp);                           /* Zeiger auf Hbit */
  218.                 n = (unsigned)(viap - (rxfhdr+L2ILEN) + (L2ILEN+L2IDLEN));
  219.                 while (n-- != 0) getchr(fbp);          /* berechnen       */
  220.                 *(fbp->mbbp - 1) |= L2CH;              /* Hbit setzen     */
  221.                 viap += L2IDLEN;                       /* Nachbardigi     */
  222.                 fbp->l2port = nbrprt(   *viap != '\0'  /* ich letzter ?   */
  223.                                       ? viap           /* nein, Port Digi */
  224.                                       : rxfhdr);       /* ja, Port Ziel   */
  225.                 fbp->l2fflg = 0;                       /* kein Linkframe  */
  226.                 sdl2fr(fbp);                           /* Frame senden    */
  227.               }
  228. #ifdef KISSMODE
  229.             else if( (crlmod == 2) && !ishost() && nmbfre > 64 )
  230.               send_to_other_port(  fbp );
  231. #endif
  232.             else              /* Frame ist noch nicht komplett digipeatet */
  233.               dealmb(fbp);    /* und/oder nix fuer mich, Frame wegwerfen  */
  234.             return (YES);     /* fuer aufrufende Funk.: Frame ist weg !   */
  235.           }
  236.         viap += L2IDLEN;      /* naechsten Digi in Digiliste untersuchen  */
  237.       }
  238.     return (NO);              /* fuer aufrufende Funk.: Frame auswerten ! */
  239.   }
  240.  
  241.  
  242.  
  243.  
  244.  
  245. /**************************************************************************\
  246. *                                                                          *
  247. * "to level 3 switch"                                                      *
  248. *                                                                          *
  249. * Aus I- oder UI-Frame (Framekopf fbp, Getzeiger/Zaehler auf 1. Byte       *
  250. * hinter Level-2-Adressfeld) PID holen, falls vorhanden. Falls es nicht    *
  251. * Level-2-PID ist, das Paket an die Level-3-Empfangsframeliste l3rxfl      *
  252. * haengen. Im Framekopf wird in jedem Fall l2fflg auf PID, wenn vorhanden, *
  253. * oder 0 gesetzt, l2link auf den aktuellen Link (lnkpoi).                  *
  254. *                                                                          *
  255. * Return:  YES - das I/UI-Frame hat ein Nicht-Level-2-PID und wurde an die *
  256. *                Level-3-Empfangsframeliste gehaengt                       *
  257. *          NO  - Frame hat Standard-Level-2-PID                            *
  258. *                                                                          *
  259. * Mheard support - added conditionally on MONITORCMD                       *
  260. *                  if function running, and if the packet contains info,   *
  261. *                  then have a look at the PID byte. Switch on it          *
  262. *                  and update associated statistic. NOTE - IMPORTANT !!    *
  263. *                  it is assumed that check_heard() has just run !!!!!!    *
  264. \**************************************************************************/
  265.  
  266. BOOLEAN tol3sw(fbp)
  267. register MBHEAD *fbp;
  268. {
  269.     fbp->l2fflg = fbp->mbgc < fbp->mbpc ? getchr(fbp) : 0; /* PID holen   */
  270.     fbp->l2link = lnkpoi;                                  /* Linkzeiger  */
  271.     if ((fbp->l2fflg & 0xFF) != L2CPID)
  272.       {                                 /* wenn nicht L2-Frame, Frame an  */
  273. #ifdef MONITORCMD
  274.  
  275.         /* if heard list enabled ( mhlcount > 0 ), and the AX25 frame shows
  276.          * that there is a valid PID in the frame, then examine it and set
  277.          * the appropriate flag bits
  278.          */
  279.         if( mhlcount && (((rxfctl & 1)==0 ) || ( (rxfctl & 0xef ) == 3 )))
  280.             switch( fbp->l2fflg & 0xff )
  281.             {
  282.                 case PID_NETROM:
  283.                     mhptr->isnode = 1;
  284.                     break;
  285. #ifdef TEXNET
  286.                 case PID_TEXNET:
  287.                     mhptr->istexnet = 1;
  288.                     break;
  289. #endif
  290.                 case PID_IP:
  291.                 case PID_ARP:
  292.                     mhptr->istcpip = 1;
  293.             }
  294. #endif
  295. #ifdef IPROUTE
  296.  
  297.         /* Now have another look and link it to the IP, ARP or L3
  298.          * receive lists as approprriate. Only accept IP frames if
  299.          * they are addressed to us !
  300.          */
  301.         switch( fbp->l2fflg & 0xff )
  302.         {
  303.             case PID_IP:
  304.                 if( cmpid( myid, rxfhdr ) )
  305.                     relink( fbp, iprxfl.tail );
  306.                 else
  307.                     return( NO );
  308.                 break;
  309.             case PID_ARP:
  310.                 relink( fbp, arprxfl.tail );
  311.                 break;
  312.             default:
  313.                 relink(fbp,l3rxfl.tail);        /* Level 3 weiterreichen          */
  314.         }
  315. #else
  316.         relink(fbp,l3rxfl.tail);        /* Level 3 weiterreichen          */
  317. #endif
  318.         return (YES);                   /* Meldung, dass weitergereicht   */
  319.       }
  320.     return (NO);                        /* Meldung, dass Level-2-Frame    */
  321. }
  322.  
  323.  
  324.  
  325.  
  326.  
  327. /**************************************************************************\
  328. *                                                                          *
  329. * "level 2 information to level x"                                         *
  330. *                                                                          *
  331. * Infopakete aus dem aktuellen Link (lnkpoi) an hoehere Level weiter-      *
  332. * reichen. nocgnc gibt an, ob der hoehere Level die "Erstickungskontrolle" *
  333. * (hier = Beruecksichtigung der maximal noch anzunehmenden I-Pakete)       *
  334. * machen soll (NO) oder in jedem Fall alle uebermittelten I-Pakete         *
  335. * annehmen muss (YES). Falls die I-Pakete vom hoeheren Level angenommen    *
  336. * wurden, Empfangszaehler rcvd und Aktivitaetstimer noatou entsprechend    *
  337. * updaten. Es wird l2link in den Framekoepfen der weitergereichten Pakete  *
  338. * auf lnkpoi gesetzt und type auf 2 fuer "Level 2".                        *
  339. *                                                                          *
  340. \**************************************************************************/
  341.  
  342. VOID i2tolx(nocgnc)
  343. unsigned nocgnc;
  344. {
  345.     register MBHEAD *rcvdip; /* Zeiger auf Framekopf weiterzureichendes I */
  346.  
  347.     while (lnkpoi->rcvd != 0)           /* solange I's aus Link vorhanden */
  348.       {
  349.         (rcvdip = lnkpoi->rcvdil.head)->l2link = lnkpoi;    /* Linkzeiger */
  350.         rcvdip->type = 2;                                   /* Level 2 !  */
  351.         if (!fmlink(nocgnc,rcvdip))     /* I an hoeheren Level geben      */
  352.           return;                       /* Abbruch, wenn nicht angenommen */
  353.         lnkpoi->noatou = ininat;        /* angenommen, wieder Aktivitaet  */
  354.         --lnkpoi->rcvd;                 /* Empfangspaketezaehler updaten  */
  355.       }
  356. }
  357.  
  358.  
  359.  
  360.  
  361.  
  362. /**************************************************************************\
  363. *                                                                          *
  364. * "serve received N(R)"                                                    *
  365. *                                                                          *
  366. * Aktuell empfangenes N(R) (rxfctl) des aktuellen Links (lnkpoi) auswerten *
  367. * und entsprechend verfahren (s.u.).                                       *
  368. *                                                                          *
  369. * Return:  YES - aktuell empfangenes N(R) ist okay oder Linkzustand        *
  370. *                laesst N(R)-Empfang nicht zu                              *
  371. *          NO  - aktuell empfangenes N(R) ist falsch                       *
  372. *                                                                          *
  373. \**************************************************************************/
  374.  
  375. BOOLEAN srxdNR()
  376.   {
  377.     register unsigned l2state;    /* Linkstatus des aktuellen Links       */
  378.     register unsigned rxdNR;      /* empfangenes N(R)                     */
  379.     register unsigned newok;      /* Anzahl neu bestaetigte I's           */
  380.     unsigned outstd;     /* Anzahl ausstehende (nicht bestaetigte) I's    */
  381.  
  382.     if ((l2state = lnkpoi->state) >= L2SIXFER)    /* darf N(R) kommen ?   */
  383.       {
  384.         if (    ( outstd = (lnkpoi->VS - lnkpoi->lrxdNR) & 0x07
  385.                 ) != 0
  386.              && ( newok = ( (rxdNR = (rxfctl >> 5) & 0x07) - lnkpoi->lrxdNR
  387.                           ) & 0x07
  388.                 ) != 0             /* N(R) nur auswerten, wenn I's aus-   */
  389.            )                       /* stehen und neue bestaetigt werden   */
  390.           if (newok <= outstd)     /* N(R) okay ?                         */
  391.             {
  392.               lnkpoi->lrxdNR = rxdNR;   /* ja, N(R) annehmen              */
  393.               clrT1();                  /* T1 stoppen                     */
  394.               if (newok != outstd)      /* wenn immer noch I's ausstehend */
  395.                 setT1();                /* T1 neu starten                 */
  396.               while (newok-- != 0)
  397.                 {                                      /* alle neu        */
  398.                   dealmb(unlink(lnkpoi->sendil.head)); /* bestaetigten    */
  399.                   --lnkpoi->tosend;                    /* I's wegwerfen   */
  400.                 }
  401.             }
  402.           else
  403.             {                           /* nein,                          */
  404.               sdfrmr(0x08);             /* Kontrollfeld hat falsches N(R) */
  405.               return (FALSE);           /* N(R) nicht okay !              */
  406.             }
  407.  
  408.         if (    l2state == L2SWA        /* falls Linkzustand "Warten auf  */
  409.              || l2state == L2SWADBS     /* Bestaetigung" ist,             */
  410.              || l2state == L2SWARBS
  411.              || l2state == L2SWABBS
  412.            )
  413.           if (!rxfCR && rxfPF != 0)          /* wenn empfangenes Frame    */
  414.             {                                /* Response mit Final war,   */
  415.               clrT1();                       /* Timer 1 stoppen und       */
  416.               lnkpoi->VS = lnkpoi->lrxdNR;   /* V(S) updaten              */
  417.             }
  418.           else                               /* sonst Timer 1 neu         */
  419.             if (!lnkpoi->T1) setT1();        /* starten falls inaktiv     */
  420.       }
  421.       
  422.     return (TRUE);                      /* N(R) okay oder nicht benutzt   */
  423.   }
  424.  
  425.  
  426.  
  427.  
  428.  
  429. /**************************************************************************\
  430. *                                                                          *
  431. * "is next I"                                                              *
  432. *                                                                          *
  433. * Testen, ob das aktuell empfangene I-Frame (rxf...) das naechste fuer den *
  434. * aktuellen Linkblock (lnkpoi) erwartete I-Frame ist, wenn der Linkzustand *
  435. * Informationstransfer zulaesst. Bei nicht erwarteter Sequenznummer        *
  436. * entsprechende Statetable abarbeiten.                                     *
  437. *                                                                          *
  438. * Return :  YES - I-Frame ist das naechste erwartete oder Linkzustand      *
  439. *                 laesst keinen Informationstransfer zu                    *
  440. *           NO  - sonst                                                    *
  441. *                                                                          *
  442. \**************************************************************************/
  443.  
  444. BOOLEAN isnxti()
  445.   {
  446.     register unsigned iseqno;                     /* I Sequence Number    */
  447.  
  448.     if (lnkpoi->state >= L2SIXFER)                        /* I-Transfer ? */
  449.       if ((iseqno = (rxfctl >> 1) & 0x07) == lnkpoi->VR)  /* I erwartet ? */
  450.         if (((lnkpoi->ltxdNR + 7) & 0x07) != iseqno)      /* kein Ueber-  */
  451.           {                                               /* lauf ?       */
  452.             if (!(lnkpoi->flag & L2FBUSY))       /* wenn nicht busy, neue */
  453.               lnkpoi->VR = (iseqno + 1) & 0x07;  /* V(R) setzen           */
  454.           }
  455.         else
  456.           {
  457.             sdfrmr(0x01);      /* Kontrollfeld falsch/nicht implementiert */
  458.             return (FALSE);
  459.           }
  460.       else                                       /* unerwartetes I (nicht */
  461.         {                                        /* naechstes in Reihe)   */
  462.           l2stma(!rxfPF ? stbl26 : stb26b);      /* INVALID N(S) RECEIVED */
  463.           return (FALSE);                        /* unerwartetes I !      */
  464.         }
  465.         
  466.     return (TRUE);       /* I richtig oder Linkzustand ohne I-Transfer    */
  467.   }
  468.  
  469.  
  470.  
  471.  
  472.  
  473. /**************************************************************************\
  474. *                                                                          *
  475. * "initialize link"                                                        *
  476. *                                                                          *
  477. * Aktuellen Linkblock (lnkpoi) initialisieren. Sequenzvariablen und Timer  *
  478. * initialisieren, Quellcall/Zielcall/via-Liste/ Port setzen aus der        *
  479. * txf...-Liste.                                                            *
  480. *                                                                          *
  481. \**************************************************************************/
  482. VOID inilnk()
  483. {
  484.     reslnk();                                /* Sequenzvars/Timer init.   */
  485.     cpyid(lnkpoi->srcid,txfhdr + L2IDLEN);   /* Quellcall                 */
  486.     cpyid(lnkpoi->dstid,txfhdr);             /* Zielcall                  */
  487.     cpyidl(lnkpoi->viaidl,txfhdr + L2ILEN);  /* via-Liste                 */
  488.     lnkpoi->liport = txfprt;                 /* Port                      */
  489.     setiT1();                                /* initial Timer 1           */
  490. }
  491.  
  492.  
  493.  
  494.  
  495. /**************************************************************************\
  496. *                                                                          *
  497. * "set initial T1"                                                         *
  498. *                                                                          *
  499. * Den initialen Timer-1-Zaehlerstand des aktuellen Linkblocks (lnkpoi)     *
  500. * (= derjenige Zaehlerstand, der bei Start des Timer 1 immer gesetzt wird) *
  501. * berechnen nach der Formel :                                              *
  502. *                                                                          *
  503. *                                                                          *
  504. *     initT1 [1/100 sec]                                                   *
  505. *                                                                          *
  506. *   = (Anzahl der Digipeater * 2 + 1) * FRACK [sec] * 100                  *
  507. *                                         |                                *
  508. *                                         +---> fuer jeden Linkblock       *
  509. * und im Linkblock setzen (initT1).             einzeln, snglT1            *
  510. *                                                                          *
  511. \**************************************************************************/
  512.  
  513. VOID setiT1()
  514. {
  515.     register char       *viap;          /* Zeiger in via-Liste            */
  516.     register unsigned    n;             /* Digizaehler                    */
  517.     
  518.     viap = lnkpoi->viaidl;              /* Anfang via-Liste               */
  519.     n = 0;                              /* noch kein Digi gezaehlt        */
  520.     while (*viap != '\0')               /* Digianzahl ermitteln           */
  521.       {
  522.         ++n;
  523.         viap += L2IDLEN;
  524.       }
  525.     n *= 2;                                       /* Digianzahl * 2 + 1   */
  526.     ++n;
  527.     lnkpoi->initT1 = lnkpoi->snglT1 * n * 100;    /* " * FRACK * 100      */
  528. }
  529.  
  530.  
  531.  
  532.  
  533.  
  534. /**************************************************************************\
  535. *                                                                          *
  536. * "messaged clear link"                                                    *
  537. *                                                                          *
  538. * Aktuellen Link aufloesen (siehe clrlnk()) und entsprechende Meldung an   *
  539. * hoehere Level geben ("Disconnected from").                               *
  540. *                                                                          *
  541. \**************************************************************************/
  542.  
  543. VOID mclrlk()
  544. {
  545.     clrlnk();                           /* Link aufloesen                 */
  546.     l2tolx(L2MDISCF);                   /* und hoehere Level informieren  */
  547. }
  548.  
  549.  
  550.  
  551.  
  552.  
  553. /**************************************************************************\
  554. *                                                                          *
  555. * "clear link"                                                             *
  556. *                                                                          *
  557. * Aktuellen Link (lnkpoi) aufloesen. Alle Sequenzvariablen und Timer       *
  558. * zuruecksetzen, Sende- und Empfangsinfoframelise loeschen, Linkblock neu  *
  559. * mit AX.25-Parametern besetzen, Anzahl der aktiven Links (nmblks) um 1    *
  560. * erniedrigen.                                                             *
  561. *                                                                          *
  562. \**************************************************************************/
  563.  
  564. VOID clrlnk()
  565. {
  566.     reslnk();                           /* Sequenzvars/Timer ruecksetzen  */
  567.     dealml(&lnkpoi->rcvdil);            /* Empfangsinfoliste loeschen     */
  568.     dealml(&lnkpoi->sendil);            /* Sendeinfoliste loeschen        */
  569.     lnkpoi->rcvd = lnkpoi->tosend = 0;  /* entsprechende Zaehler loeschen */
  570.     --nmblks;                           /* nun ein aktiver Link weniger   */
  571.     inilbl();                           /* Linkblock "frisch"             */
  572. }
  573.  
  574.  
  575.  
  576.  
  577.  
  578. /**************************************************************************\
  579. *                                                                          *
  580. * "disconnect"                                                             *
  581. *                                                                          *
  582. * Disconnect des aktuellen Links (lnkpoi) einleiten. Alle Sequenzvariablen *
  583. * und Timer zuruecksetzen, DISC senden, neuer Status "Disconnect request". *
  584. *                                                                          *
  585. \**************************************************************************/
  586.  
  587. VOID disc()
  588. {
  589.     reslnk();                           /* Sequenzvars/Timer ruecksetzen  */
  590.     xdisc();                            /* DISC senden                    */
  591.     lnkpoi->state = L2SDSCRQ;           /* Linkstatus "Disc Request"      */
  592. }
  593.  
  594.  
  595.  
  596.  
  597.  
  598. /**************************************************************************\
  599. *                                                                          *
  600. * "reset link"                                                             *
  601. *                                                                          *
  602. * Aktuellen Link (lnkpoi) zuruecksetzen. Alle Sequenzvariablen und Timer   *
  603. * initialisieren.                                                          *
  604. *                                                                          *
  605. \**************************************************************************/
  606.  
  607. VOID reslnk()
  608. {
  609.        lnkpoi->VS
  610.      = lnkpoi->VR
  611.      = lnkpoi->ltxdNR
  612.      = lnkpoi->lrxdNR
  613.      = lnkpoi->flag
  614.      = 0;
  615.      clrT1();
  616.      clrT2();
  617. }
  618.  
  619.  
  620.  
  621.  
  622.  
  623. /**************************************************************************\
  624. *                                                                          *
  625. * "initialize link block"                                                  *
  626. *                                                                          *
  627. * Aktuellen Linkblock (lnkpoi) mit AX.25-Parametern initialisieren.        *
  628. * Loeschen des Quellrufzeichens, Setzen von FRACK, MAXFRAME, RETRY,        *
  629. * AX25V2.                                                                  *
  630. *                                                                          *
  631. \**************************************************************************/
  632.  
  633. VOID inilbl()
  634. {
  635.     *lnkpoi->srcid  = '\0';
  636.     lnkpoi->snglT1  = Fpar;
  637.     lnkpoi->k       = Opar;
  638.     lnkpoi->N2      = Npar;
  639.     lnkpoi->V2link  = Vpar;
  640. }
  641.  
  642.  
  643.  
  644.  
  645.  
  646. /**************************************************************************\
  647. *                                                                          *
  648. * "send outstanding I's"                                                   *
  649. *                                                                          *
  650. * Aus dem aktuellen Linkblock (lnkpoi) soviele I-Frames senden, wie im     *
  651. * Moment unbestaetigt ausstehen.                                           *
  652. *                                                                          *
  653. \**************************************************************************/
  654.  
  655. VOID sdoi()
  656. {
  657.     register unsigned nmbtos;           /* Anzahl I's zu senden           */
  658.     
  659.     if (nmbtos = (lnkpoi->VS - lnkpoi->lrxdNR) & 0x07) /* wieviel darf    */
  660.       {                                                /* ich ?           */
  661.         lnkpoi->VS = lnkpoi->lrxdNR;                   /* V(S) resetten   */
  662.         sdi(nmbtos);                                   /* I's senden      */
  663.       }
  664. }
  665.  
  666.  
  667.  
  668.  
  669.  
  670. /**************************************************************************\
  671. *                                                                          *
  672. * "send I"                                                                 *
  673. *                                                                          *
  674. * Aus dem aktuellen Linkblock (lnkpoi) maximal max I-Frames aus der        *
  675. * Infomessageliste aufbauen und senden. Infos ueber 256 Bytes werden       *
  676. * gesplittet und dann gesendet. Die Frames werden als Commandframes ohne   *
  677. * Poll/Final-Bit gesendet. V(S) wird fuer jedes gesendete Frame erhoeht    *
  678. * modulo 7. Timer 2 und Timer 3 werden abgeschaltet.                       *
  679. *                                                                          *
  680. \**************************************************************************/
  681.  
  682. VOID sdi(max)
  683. unsigned max;
  684. {
  685.     register unsigned    n;                  /* Zaehler zu sendende Infos */
  686.     register MBHEAD     *sendip;             /* Kopfzeiger Infobuffer     */
  687.     register MBHEAD     *fbp;                /* Kopfzeiger Framebuffer    */
  688.  
  689.     for ( n = 0, sendip = lnkpoi->sendil.head;    /* maximal max I-Frames */
  690.           n < lnkpoi->tosend && n < max;          /* aus der Linkblock-   */
  691.           ++n, sendip = sendip->nextmh            /* infoliste senden     */
  692.         )                                         /* wenn vorhanden       */
  693.       {
  694.         stxfad();                            /* Frameadresse aufbauen     */
  695.         txfV2 = lnkpoi->V2link;              /* Version                   */
  696.         txfCR = L2CCR;                       /* Command !                 */
  697.         txfPF = 0;                           /* kein Poll/Final           */
  698.         txfctl = setNR(lnkpoi->VS << 1);     /* Controlbyte I setzen      */
  699.         ++lnkpoi->VS;                        /* V(S) erhoehen             */
  700.         lnkpoi->VS &= 0x07;                  /* modulo 7                  */
  701.         putchr(sendip->l2fflg,               /* Frame aufbauen, PID       */
  702.                fbp = makfhd(L2FT1ST));
  703. #ifdef MODIFIED
  704.  
  705.         /* in modified version, to permit big frames, only permit splitting
  706.          * if the packet is NOT a higher layer protocol !
  707.          */
  708.         if( splcpy( 256, fbp, sendip, sendip->l2fflg == L2CPID ) 
  709.           /*==YES*/ )                        /* Message hineinkopieren    */
  710. #else
  711.         if(splcpy(256,fbp,sendip) /*==YES*/) /* Message hineinkopieren    */
  712. #endif
  713.           ++lnkpoi->tosend;                  /* falls Split eine mehr     */
  714.         sdl2fr(fbp);                         /* Frame senden              */
  715.         clrT2();                             /* Timer 2 abschalten        */
  716.         clrT3();                             /* Timer 3 abschalten        */
  717.       }
  718. }
  719.  
  720.  
  721.  
  722.  
  723.  
  724. /**************************************************************************\
  725. *                                                                          *
  726. * "split copy"                                                             *
  727. *                                                                          *
  728. * Die Bytes aus dem Messagebuffer, auf dessen Kopf mbhd zeigt, in den      *
  729. * Framebuffer, auf dessen Kopf fbp zeigt, kopieren. Es werden hoechstens   *
  730. * max Bytes kopiert, hat die Message mehr Bytes, so wird ein neuer         *
  731. * Messagebuffer angelegt, die restlichen Messagebytes werden in diesen     *
  732. * Buffer kopiert, der neue Buffer wird hinter den alten Messagebuffer      *
  733. * gehaengt, der Putcount des alten Buffers wird auf max gestellt, das      *
  734. * "more follows"-Flag morflg des neuen Buffers wird geloescht, l2fflg wird *
  735. * uebertragen.                                                             *
  736. *                                                                          *
  737. * Return :  YES - der Messagebuffer wurde aufgesplittet                    *
  738. *           NO  - sonst                                                    *
  739. *                                                                          *
  740. * This modified version adds a boolean parameter to say whether it is      *
  741. * OK to split the frame or not.                                            *
  742. \**************************************************************************/
  743.  
  744. #ifdef MODIFIED
  745. BOOLEAN splcpy(max,fbp,mbhd, can_be_split)
  746. unsigned    max;
  747. MBHEAD     *fbp;
  748. register MBHEAD     *mbhd;
  749. BOOLEAN can_be_split;
  750. #else
  751. BOOLEAN splcpy(max,fbp,mbhd )
  752. unsigned    max;
  753. MBHEAD     *fbp;
  754. register MBHEAD     *mbhd;
  755. #endif
  756.   {
  757.     char       *mbbpsa;                 /* Sicherung mbbp                 */
  758.     BOOLEAN     split;                  /* TRUE: Split erfolgt            */
  759.     unsigned    mbgcsa;                 /* Sicherung mbgc                 */
  760.     unsigned    mbgc2;                  /* mbgc alt -> mbpc alt           */
  761.     register unsigned    n;             /* Zaehler                        */
  762.     register MBHEAD     *mbhd2;         /* Kopfzeiger neuer Messagebuffer */
  763.     
  764.     split = NO;                         /* zunaechst nichts gesplittet    */
  765.     mbbpsa = mbhd->mbbp;                /* Bufferpointer sichern          */
  766.     mbgcsa = mbhd->mbgc;                /* Getcounter sichern             */
  767. #ifdef MODIFIED
  768.     n = mbhd->mbpc - mbhd->mbgc;
  769.     if( n > max && can_be_split )
  770.         n = max;
  771.     while( n-- )
  772. #else
  773.     for (n = 0; mbhd->mbgc < mbhd->mbpc && n < max; ++n)
  774. #endif
  775.       putchr(getchr(mbhd),fbp);         /* maximal max Bytes kopieren     */
  776.     if (mbhd->mbgc < mbhd->mbpc)        /* noch Bytes ueber -> Split !    */
  777.       {
  778.         mbgc2 = mbhd->mbgc;             /* Getcount fuer spaeter merken   */
  779.         mbhd2 = allocb();               /* neuen Buffer erzeugen          */
  780. #ifdef MODIFIED
  781.         mhtyp_copy( mbhd, mbhd2 );
  782. #else
  783.         while (mbhd->mbgc < mbhd->mbpc) /* die restlichen Bytes in diesen */
  784.           putchr(getchr(mbhd),mbhd2);   /* Buffer kopieren                */
  785. #endif
  786.         rwndmb(mbhd2);                  /* neuen Buffer rewinden          */
  787.         mbhd2->morflg = NO;             /* noch dem neuen folgt keiner    */
  788.         mbhd2->l2fflg = mbhd->l2fflg;   /* Frameflag uebertragen          */
  789.         relink(mbhd2,mbhd);             /* neu. Buf. hinter alten haengen */
  790.         mbhd->mbpc = mbgc2;             /* alter Buffer nur max Zeichen ! */
  791.         split = YES;                    /* wir mussten splitten           */
  792.       }
  793.     mbhd->mbbp = mbbpsa;                /* Bufferpointer restaurieren     */
  794.     mbhd->mbgc = mbgcsa;                /* Getcount restaurieren          */
  795.     return (split);                     /* Split oder nicht               */
  796.   }
  797.  
  798.  
  799.  
  800.  
  801.  
  802. /**************************************************************************\
  803. *                                                                          *
  804. * "send UI"                                                                *
  805. *                                                                          *
  806. * UI-Frame aufbauen und senden. Das UI-Frame wird an ID dest geschickt     *
  807. * ueber den Port port und die via-Liste (nullterminiert) vial, als Quelle  *
  808. * wird source genommen, die Infobytes des Frames stehen im Messagebuffer,  *
  809. * auf dessen Kopf mbhd zeigt, die PID wird aus l2fflg dieses Buffers       *
  810. * genommen.                                                                *
  811. *                                                                          *
  812. \**************************************************************************/
  813.  
  814. VOID sdui(vial,dest,source,port,mbhd)
  815. char     *vial;
  816. char     *dest;
  817. char     *source;
  818. unsigned  port;
  819. register MBHEAD   *mbhd;
  820.   {
  821.     register MBHEAD *fbp;                         /* Zeiger auf Framekopf */
  822.  
  823.     cpyid(txfhdr + L2IDLEN,source);               /* Quelle setzen        */
  824.     cpyid(txfhdr,dest);                           /* Ziel setzen          */
  825.     cpyidl(txfhdr + L2ILEN,vial);                 /* via-Liste setzen     */
  826.     txfprt = port;                                /* Port setzen          */
  827.     txfV2 = Vpar;                                 /* Protokollversion     */
  828.     txfCR = L2CCR;                                /* Command !            */
  829.     txfPF = 0;                                    /* kein Poll/Final      */
  830.     txfctl = L2CUI;                               /* UI-Frame !           */
  831.     putchr(mbhd->l2fflg,fbp = makfhd(0));         /* Frame aufbauen, PID  */
  832. #ifdef MODIFIED
  833.     mhtyp_copy( mbhd, fbp );
  834. #else
  835.     while (mbhd->mbgc < mbhd->mbpc)               /* Message -> Frame     */
  836.       putchr(getchr(mbhd),fbp);
  837. #endif
  838.     sdl2fr(fbp);                                  /* Frame senden         */
  839.   }
  840.  
  841.  
  842.  
  843.  
  844.  
  845. /**************************************************************************\
  846. *                                                                          *
  847. * "level 2 state machine"                                                  *
  848. *                                                                          *
  849. * Ausfuehren der Zustandsuebergangsfunktion des Linkstatus (state) des     *
  850. * aktuellen Linkblocks (lnkpoi) in der Statetable stbl, danach einnehmen   *
  851. * des durch die Statetable gegebenen neuen Zustands.                       *
  852. *                                                                          *
  853. * In der Protokollversion 1 (dort gibt es nur 5 Zustaende), alle Zustaende *
  854. * oberhalb Informationstransfer auf Informationstransfer setzen.           *
  855. *                                                                          *
  856. \**************************************************************************/
  857.  
  858. VOID l2stma(stbl)
  859. register STENTRY stbl[];
  860. {
  861.     (*stbl[lnkpoi->state].func)();                     /* Funktion ...    */
  862.     lnkpoi->state = stbl[lnkpoi->state].newstate;      /* neuer Zustand   */
  863.     if (!lnkpoi->V2link && lnkpoi->state > L2SIXFER)   /* Version 1       */
  864.       lnkpoi->state = L2SIXFER;                        /* Stutzung        */
  865. }
  866.  
  867.  
  868.  
  869. /* Ende von L2B.C */
  870.